//
//  XZNetworkManager.swift
//  JiuCheYue
//
//  Created by 刘表聪 on 2018/4/12.
//  Copyright © 2018年 xinzhen. All rights reserved.
//

import UIKit
import Alamofire
import SwiftyJSON

typealias RHRequestSuccessCallback = ((_ message: String?, _ model: Any?) -> Void)
typealias RHRequestFailureCallback = ((_ code: Int?,_ message: String?) ->Void)
typealias RHRequestDestinationCallback = ((_ url: URL,_ urlResponse: HTTPURLResponse)->(destinationURL: URL, options: DownloadRequest.DownloadOptions))
typealias RHRequestProgressCallback = ((_ progress: Progress) -> Void)
typealias RHRequestDownloadCallback = ()->Void


class RHNetworkManager: NSObject {
    private var baseURL: String = "http://mobile.mf-data.com/api/v1"
    private var baseURL2: String = "http://api.mf-data.com/api/v1"
    private var appSecret: String?
    private var appKey: String?
    private var appVersion: String?
    private var token: String?
    private lazy var manager: SessionManager = {
        let configuration = URLSessionConfiguration.default
        
        return Alamofire.SessionManager(configuration: configuration)
    }()
    
    // MARK: @singleton
    static let sharedInstance: RHNetworkManager = { RHNetworkManager() }()
    
    override init() {
        super.init()
    }
    
    /**
     *  设置userid
     */
    func setupUserToken(token: String?) {
        self.token = token
    }
    
    /**
     *  配置baseUrl
     */
    func setupBaseURL(baseURL: String?) {
        self.baseURL = baseURL != nil ? baseURL! : ""
    }
    
 
    func cancelRequest() {
        if #available(iOS 9.0, *) {
            self.manager.session.getAllTasks { (tasks) in
                tasks.forEach{ $0.cancel() }
            }
        } else {
            self.manager.session.getTasksWithCompletionHandler({ (sessionDataTask, uploadData, downloadData) in
                sessionDataTask.forEach { $0.cancel() }
                uploadData.forEach { $0.cancel() }
                downloadData.forEach { $0.cancel() }
            })
        }
    }
    
    // MARK: @RequestHTTPMethod
    func requestWithEndpoint<T: Decodable>(endpoint: String, method: HTTPMethod, header: [String: String]?, parameters: [String: Any]?, modelType: T.Type, isEncryption: Bool, isData: Bool, success: RHRequestSuccessCallback?, failure: RHRequestFailureCallback?) {

        let defaultHeader: HTTPHeaders
        if RHAppUserProfile.sharedInstance.hasLoggedIn() {
            defaultHeader = [
                "User-Agent": "iPhone",
                "token": RHAppUserProfile.sharedInstance.userToken!]
        }else{
            defaultHeader = [
                "User-Agent": "iPhone"]
        }
        
        let url = isEncryption == false ? baseURL : baseURL2
        self.manager.request((url + endpoint), method: method, parameters: parameters, headers: defaultHeader)
            .responseData { [weak self](response) in
            guard let weakSelf = self else { return }
            
            let json = try? JSON(data: (response.data != nil ? response.data! : Data()))
            print("===URL=====", url + endpoint)
            print("===response=====", json?.dictionary ?? [:])
            if !(response.error != nil && (response.error! as NSError).code == -999) {
                if !weakSelf.validateRepsonse(response: json?.dictionary, failure: failure) {return}
            }
            
            var modelData = try? json![].rawData()
            if isData{
                modelData = try? json!["data"].rawData()
            }
            
            switch response.result {
            case .success(_):
                do {
                    if json!["status"].int == 0{
                        let decoder = JSONDecoder()
                        if modelData == nil {
                            modelData = try? json![].rawData()
                        }
                        let baseModel = try? decoder.decode(modelType, from: modelData!)
                        if baseModel != nil {
                            success?(json!["msg"].stringValue, baseModel)
                        }else {
                            failure?(json!["status"].int, "json解析失败")
                        }
                    }else {
                        failure?(json!["status"].int, json!["msg"].stringValue)
                    }
                    return
                }
                
            case .failure(let error as NSError):
                let message =  error.localizedDescription.count > 0 ? error.localizedDescription : "网络请求错误"
                
                failure?(error.code, message)
                NotificationCenter.default.post(name: NSNotification.Name(RHAppErrorNotification), object: nil, userInfo: ["error":["code":error.code,"message":message]])
                break
            }
                
        }
    }
    
    func uploadWithEndpoint(endpoint: String, data: Data, fileName: String, success: RHRequestSuccessCallback?, failure: RHRequestFailureCallback?) {
        let defaultHeader: HTTPHeaders
        if RHAppUserProfile.sharedInstance.hasLoggedIn() {
            defaultHeader = [
                "User-Agent": "iPhone",
                "token": RHAppUserProfile.sharedInstance.userToken!]
        }else{
            defaultHeader = [
                "User-Agent": "iPhone",]
        }
        
        self.manager.upload(multipartFormData: { (multipartFormData) in
            let dateformatter =  DateFormatter()
            dateformatter.dateFormat = "yyyyMMddHHmmss"
            let fileNameDate = "myFile"

            
            multipartFormData.append(data, withName: "file", fileName: "\(fileName)\(fileNameDate).jpg", mimeType: "image/*")
        }, to: (baseURL + endpoint), method: .post, headers: defaultHeader) { (encodingResult) in
            switch encodingResult {
            case .success(let upload, _, _):
                upload.uploadProgress { progress in // 进度
                    print(Float(progress.fractionCompleted))
                }
                upload.validate()
                upload.responseJSON { [weak self]response in
                    guard let weakSelf = self else { return }
                    let json = try? JSON(data: (response.data != nil ? response.data! : Data()))
                    print("===upload=====%@", json?.dictionary ?? [:])
                    if !weakSelf.validateRepsonse(response: json?.dictionary, failure: failure) {return}
                    switch response.result {
                    case .success(_):
                        success?(json!["msg"].stringValue, json!["data"].string)
                        return;
                    case .failure(let error as NSError):
                        let message =  error.localizedDescription.count > 0 ? error.localizedDescription : "网络请求错误"
                        failure?(error.code, message)
                        NotificationCenter.default.post(name: NSNotification.Name(RHAppErrorNotification), object: nil, userInfo: ["error":["code":error.code,"message":message]])
                        break
                    }
                }
            case .failure(let error as NSError):
                let message =  error.localizedDescription.count > 0 ? error.localizedDescription : "上传失败"
                
                failure?(error.code, message)
                NotificationCenter.default.post(name: NSNotification.Name(RHAppErrorNotification), object: nil, userInfo: ["error":["code":error.code,"message":message]])
                break
            }
        }
        
    }

    private func validateRepsonse(response: [String: JSON]?, failure: RHRequestFailureCallback?) -> Bool {
        var errorMessage: String = ""
        if response != nil {
            if (!response!.keys.contains("msg")) {
                errorMessage = "网络异常，请稍后重试"
            } else if (!response!.keys.contains("data")) {
                errorMessage = "网络异常，请稍后重试"
            }
        } else {
            errorMessage = "网络异常，请稍后重试"
        }
        
        if (errorMessage.count > 0) {
            var code: Int = 999
            if  response != nil && response!["code"] != nil {
                code = response!["code"]!.int!
            }
            NotificationCenter.default.post(name: NSNotification.Name(RHAppErrorNotification), object: nil, userInfo: ["error":["code":code,"message":errorMessage]])
            
            failure?(code , errorMessage)
            return false
        }
        return true;
    }

}




